package com.cxyjy.cfyuiapi.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cxyjy.cfyuiapi.service.ViewService;
import com.cxyjy.common.util.JObjectUtil;
import com.cxyjy.common.util.JRequestUtil;
import com.cxyjy.common.util.JResponse;
import com.cxyjy.common.util.ResultUtil;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.cxyjy.common.constants.CfyuiConstants.*;
import static com.cxyjy.common.util.ResultCode.*;

@Service("ViewService")
public class ViewServiceImpl implements ViewService {
    /**
     * 预览图片和视频,除了fileName参数都可以为空
     *
     * @param promptId
     * @return
     * @throws IOException
     * @throws NoSuchMethodException
     */
    @Override
    public JResponse view(String promptId) throws IOException {
        URL url = new URL(JObjectUtil.stringValue(HISTORY_URL) + "/" + promptId);
        Object data = JRequestUtil.sendGetRequest(url, null);
        if(JObjectUtil.isEmpty(data)) {
            if(isPromptIdInvalid(promptId)){
                return ResultUtil.error(GET_WRONG_PROMPT_ID);
            }else {
                return ResultUtil.error(WORKFLOW_STILL_IN_PROGRESS);
            }
        }
        JSONObject dataJO = JSONObject.parseObject(JSON.toJSONString(data));
        JSONObject outputsImagesJO = JSONObject.parseObject(JSON.toJSONString(dataJO.getJSONObject(promptId)
                .getJSONObject("outputs")
                .getJSONObject("125")
                .getJSONArray("images")
                .get(0)));
        String filename = outputsImagesJO.getString("filename");
        String type = outputsImagesJO.getString("type");
        String outputImageUrlStr = JObjectUtil.stringValue(VIEW_URL) + "?filename=" + filename+"&type="+type;
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("url", outputImageUrlStr);
        return ResultUtil.success(resultMap);
    }

    /**
     * 当查询出来的结果为空时
     *
     * 判断是用户输入的promptId错误，还是视频仍在生成当中
     * queue_running是正在运行的工作流 queue_pending是在排队的工作流
     * 两者之中都没有才能判定是用户输入的promptId错误
     *
     * @param promptId
     * @return false:promptId不是非法的，工作流在运行或者排队   true:promptId非法
     * @throws IOException
     */
    private boolean isPromptIdInvalid(String promptId) throws IOException {
            Map<String, Object> queueMap = JObjectUtil.toMap(JRequestUtil.sendGetRequest(QUEUE_URL, null));
            List<List> runningList = JObjectUtil.jsonArrayToList(JObjectUtil.stringValue(queueMap.get("queue_running")), List.class);
            List<List> pendingList = JObjectUtil.jsonArrayToList(JObjectUtil.stringValue(queueMap.get("queue_pending")), List.class);
            //正在进行的工作流是否有该promptId？有的话证明promptId是有效的只是还没跑完
            if (!runningList.isEmpty()) {
                if (runningList.get(0).get(1).equals(promptId)) {
                    return false;
                }
                //检查排队的工作流是否有该promptId
                if(!pendingList.isEmpty()){
                    for(List<String> promptList : pendingList){
                        if(promptList.get(1).equals(promptId)){
                            return false;
                        }
                    }
                }
            }
            //都不是，那就是非法promptId，用户输入错了
            return true;
    }
    /**
     * 根据promptId预览视频
     * @param promptId
     * @return
     * @throws IOException
     */
    @Override
    public JResponse viewVideo(String promptId) throws IOException {
        if (JObjectUtil.isEmpty(promptId) || promptId.equals("undefined")) {
            return ResultUtil.error(10002, "请先完成上传图片生成视频流程！");
        }
        //使用comfyui /history接口查询工作流的信息
        URL url = new URL(JObjectUtil.stringValue(HISTORY_URL) + "/" + promptId);
        Object data = JRequestUtil.sendGetRequest(url, null);

        if(JObjectUtil.isEmpty(data)) {
            if(isPromptIdInvalid(promptId)){
                return ResultUtil.error(GET_WRONG_PROMPT_ID);
            }else {
                return ResultUtil.error(WORKFLOW_STILL_IN_PROGRESS);
            }
        }
        Map<String, Object> dataMap = JObjectUtil.toMap(data);
        Map<String, Map<String, List<String>>> outputsMap = new HashMap<>();
        try {
            Map<String, Object> historyMap = JObjectUtil.toMap(dataMap.get(promptId));
            outputsMap = (Map<String, Map<String, List<String>>>) historyMap.get("outputs");
        } catch (NullPointerException e) {
            return ResultUtil.error(WORKFLOW_STILL_IN_PROGRESS);
        }
        if (outputsMap.isEmpty()) return ResultUtil.error(WORKFLOW_STILL_IN_PROGRESS);
        Path videoFilePath = null;
        try{
            videoFilePath = Paths.get(outputsMap.get("108").get("text").get(0));//目前换脸完整视频从108号节点出
        }catch (NullPointerException e){
            e.printStackTrace();
            return ResultUtil.error(COMFYUI_VIDEO_GENERATE_ERROR);
        }
        String videoFileName = JObjectUtil.stringValue(videoFilePath.getFileName()).replace("\"", "");
        /**
         * 现在comfyui路径没有暴露给公网，必须从外网访问然后走nginx代理
         */
        String outputVideoUrlStr = JObjectUtil.stringValue(VIEW_URL) + "?filename=" + videoFileName;
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("url", outputVideoUrlStr);
        return ResultUtil.success(resultMap);
    }

    @Override
    public JResponse viewVideoTest(String promptId) throws IOException {
        if (JObjectUtil.isEmpty(promptId) || promptId.equals("undefined")) {
            return ResultUtil.error(10002, "请先完成上传图片生成视频流程！");
        }
        URL url = new URL(JObjectUtil.stringValue(HISTORY_URL) + "/" + promptId);
        Object data = JRequestUtil.sendGetRequest(url, null);
        Map<String, Object> dataMap = JObjectUtil.toMap(data);
        Map<String, Map<String, Object>> outputsMap = new HashMap<>();
        try {
            Map<String, Object> historyMap = JObjectUtil.toMap(dataMap.get(promptId));
            outputsMap = (Map<String, Map<String, Object>>) historyMap.get("outputs");
        } catch (NullPointerException e) {
            return ResultUtil.error(WORKFLOW_STILL_IN_PROGRESS);
        }

        Map<String, Object> paramsMap = new HashMap<>();
        if (!outputsMap.isEmpty()) {
            //避免输出了多个视频造成的麻烦，只取第一个视频的信息
            Map.Entry<String, Map<String, Object>> entry = outputsMap.entrySet().iterator().next();
            Map<String, List> digitMap = (Map) entry.getValue();
            paramsMap = JObjectUtil.toMap(digitMap.get("gifs").get(0));
        }
        URL getRequestURL = JRequestUtil.createGetRequestURL(VIEW_URL, paramsMap);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("url", JObjectUtil.stringValue(getRequestURL));
        return ResultUtil.success(resultMap);
    }

    @Override
    public JResponse viewVideoByLocalFile(Map<String, Object> paramsMap) throws IOException {
        File file = new File(JObjectUtil.stringValue(JRequestUtil.sendGetRequest(VIEW_URL, paramsMap)));
        String fileName = file.getName();
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("path", "video/" + fileName);
        return ResultUtil.success(resultMap);
    }

    @Override
    public String getFileName(Map<String, Object> paramsMap) throws IOException {
        File file = new File(JObjectUtil.stringValue(JRequestUtil.sendGetRequest(VIEW_URL, paramsMap)));
        String fileName = file.getName();
        return fileName;
    }


}
